package com.example.demo.verify.validator;

import com.example.demo.verify.ParamValid;
import com.example.demo.common.Valid;
import com.example.demo.common.constant.RuleCode;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Arrays;
import java.util.List;

public class ParamValidValidator implements ConstraintValidator<ParamValid, Object> {
    private String name;
    private int rule;
    private int min;
    private int max;
    private String item;
    private String message;
    private boolean empty;

    @Override
    public void initialize(ParamValid param) {
        this.name = param.name();
        this.rule = param.rule();
        this.min = param.min();
        this.max = param.max();
        this.item = param.item();
        this.message = param.message();
        this.empty = param.empty();
    }

    @Override
    public boolean isValid(Object obj, ConstraintValidatorContext context) {
        // 1、允许字段为空，在非空时才校验
        if (this.empty) {
            if (obj == null) {
                setTip(context, "不能为null");
                return false;
            }
            if (obj.toString().trim().isEmpty()) {
                return true;
            }
        }
        else {
            // 不能为null或为空
            if (obj == null || obj.toString().trim().isEmpty()) {
                setTip(context, "不能为空");
                return false;
            }
        }

        // 2、经过第1步的非空校验，到这里字段已不为空，若指定校验规则只是noEmpty，可直接返回成功标识
        if (this.rule == RuleCode.noEmpty) {
            return true;
        }

        // 3、根据规则类型进行校验（文本内容需进行SQL注入校验）
        String value = obj.toString().trim();
        if (this.rule == RuleCode.noWick) {
            if (Valid.isWicked(value)) {
                setTip(context, "不能有特殊字符");
                return false;
            }
        }
        else if (this.rule == RuleCode.phone) {
            setTip(context, "格式不正确");
            return Valid.isPhone(value);
        }
        else if (this.rule == RuleCode.email) {
            if (!Valid.isEmail(value)) {
                setTip(context, "格式不正确");
                return false;
            }
        }
        else if (this.rule == RuleCode.mobile) {
            setTip(context, "格式不正确");
            return Valid.isMobile(value);
        }
        else if (this.rule == RuleCode.contact) {
            setTip(context, "格式不正确");
            return Valid.isContact(value);
        }
        else if (this.rule == RuleCode.num) {
            setTip(context, "格式不正确");
            return Valid.isNum(value);
        }
        else if (this.rule == RuleCode.money) {
            setTip(context, "格式不正确");
            return Valid.isMoney(value);
        }
        else if (this.rule == RuleCode.date) {
            setTip(context, "格式不正确");
            return Valid.isDate(value);
        }
        else if (this.rule == RuleCode.base64) {
            setTip(context, "格式不正确");
            return Valid.isBase64(value);
        }
        else if (this.rule == RuleCode.url) {
            if (!Valid.isUrl(value)) {
                setTip(context, "格式不正确");
                return false;
            }
        }
        else if (this.rule == RuleCode.select) {
            if (Valid.isEmpty(item)) {
                setTip(context, "的可选项为空");
                return false;
            }
            List<String> list = Arrays.asList(item.split("\\|"));
            if (!list.contains(value)) {
                setTip(context, "格式不正确");
                return false;
            }
            return true;
        }
        else if (this.rule == RuleCode.range) {
            setTip(context, "的数值超出范围区间");
            return Valid.isRange(value, min, max);
        }
        else if (this.rule == RuleCode.length) {
            setTip(context, "的长度超出范围区间");
            return Valid.isLength(value, min, max);
        }
        else {
            setTip(context, "的校验规则出错，请排查");
            return false;
        }

        // 4、SQL注入校验（只有 noWick、email、url 三种情况可执行到这一步）
        setTip(context, "包含SQL字符");
        return !Valid.isSqlInject(value);
    }

    private void setTip(ConstraintValidatorContext context, String tip) {
        String msg = Valid.isEmpty(this.message) ? this.name + tip : this.message;
        context.disableDefaultConstraintViolation();
        context.buildConstraintViolationWithTemplate(msg).addConstraintViolation();
    }
}
